<?php
declare(strict_types=1);

namespace app\common\model;

use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use Exception;
use think\facade\Db;
use think\facade\Session;
use think\Hashlib;
use think\Model;
use think\model\relation\BelongsTo;
use think\model\relation\HasMany;
use think\facade\Log;
use think\SnowflakeIdWorker;

/**
 * | Notes：用户模型
 * +----------------------------------------------------------------------
 * | PHP Version 7.2+
 * +----------------------------------------------------------------------
 * | Copyright (c) 2011-2020 https://www.xxq.com.cn, All rights reserved.
 * +----------------------------------------------------------------------
 * | Author: 和好 <389123492@qq.com>
 * +----------------------------------------------------------------------
 * | Date: 2020/4/27 15:23
 * +----------------------------------------------------------------------
 */
class Member extends Base
{
    // 设置模型名称
    // protected $name       = 'member';

    // 设置主键
    // protected $pk         = 'id';

    // 定义默认的表后缀（默认查询中文数据）
    // protected $suffix     = '_cn';

    // 设置当前模型对应的完整数据表名称
    // protected $table      = 'think_member';

    // 设置当前模型的数据库连接
    // protected $connection = 'db_config';

    // 设置只读字段
    protected $readonly = ['number'];

    // 设置字段信息
    protected $schema = [];

    // 设置字段自动转换类型
    protected $type = [
        'id'          => 'int',
    ];

    // 设置废弃字段
    // protected $disuse     = [ 'status', 'type' ];

    // 模型数据不区分大小写
    // protected $strict     = false,

    // 模型初始化
    // protected static function init()
    // {
    //     //TODO:初始化内容
    // }

    /**
     * 新增前
     *
     * @param Model $data
     *
     * @return mixed|void
     * @throws Exception
     */
    public static function onBeforeInsert(Model $data)
    {
        $hashlib = new Hashlib();

        $idWorker = new SnowflakeIdWorker();
        $number = $idWorker->nextId();
        $code = $hashlib->encode($number);
        $data->code = $code;
        $data->number = $number;
        $data->status = 1;
        $data->reister_ip = request()->ip();
        $data->create_time = date('Y-m-d H:i:s');
        $data->update_time = date('Y-m-d H:i:s');
    }

    /**
     * 更新前
     *
     * @param Model $data
     */
    public static function onBeforeUpdate(Model $data)
    {
        // 更新登录信息
        $data->login_num = Db::raw('login_num+1');
        $data->login_ip = request()->ip();
        $data->update_time = date('Y-m-d H:i:s');
    }


    /**
     * 更新用户
     *
     * @param int   $uuid
     * @param array $data
     *
     * @return bool
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public static function updateMember(int $uuid, array $data): bool
    {
        $member = self::find($uuid);
        return $member->save($data);
    }

    /**
     * 用户关联信息
     *
     * @param int $uuid
     * @param int $client_type
     *
     * @return array
     */
    public static function getMemberWithInfo(int $uuid, int $client_type): array
    {
        $member_wdth_data = self::with([
        ])
            ->field('id, mobile,  number,  nickname, member_group_id, money,  safety_code, code,  active_time, expire_time, create_time, portrait, account_address','status')
            ->findOrEmpty($uuid)
            ->toArray();
        $member_wdth_data['number'] = empty($member_wdth_data['number']) ? '' : substr($member_wdth_data['number'], 5);
        //关联查询
        return $member_wdth_data;
    }

    /**
     * 用户登录认证
     *
     * @param int    $client_type     客户端类型
     * @param int    $type            账户类型
     * @param string $loginId         账户ID
     * @param string $password        密码
     * @param int    $auth_login_type 授权类型
     * @param string $module          授权名称
     *
     * @return array|int|Model
     */
    public function login(int $type = 6, $loginId = '', $password = '', int $auth_login_type = 0, string $module = 'admin', int $client_type = 1)
    {
        switch ($type) {
            case 1:
                $sqlmap = 'id';
                break;
            case 2:
                $sqlmap = 'number';
                break;
            case 3:
                $sqlmap = 'mobile';
                break;
            case 4:
                $sqlmap = 'username';
                break;
            case 6:
                $sqlmap = 'number|mobile|email';
                break;
            default:
                return 0; //参数错误
        }

        //关联查询
        $member_obj = $this->whereOr($sqlmap, $loginId)
            ->field('id, number, mobile,appinit_type, money, password, status, create_time')
            ->findOrEmpty();

        // 未注册
        if ($member_obj->isEmpty()) return -1;

        // 账户已被冻结
        if ($member_obj->status == 0) return -2;

        // 账户待注销
        if ($member_obj->status == 2) return -3;

        if ($auth_login_type == 1) {
            //密码错误
            if (sha1($password) !== $member_obj['password']) return -4;
        } elseif ($auth_login_type == 2) {
            /*$smsauth = Session::get('sms_secret_key');
            log_file($smsauth, 'member_model', 'member_model');
            //验证码错误
            if (empty($smsauth) || (md5($loginId . $password) !== $smsauth['encryption']) || !isset($smsauth['send_time']) || $smsauth['send_time'] < time()) return -5;*/
        } elseif ($auth_login_type == 3) {
            // 邮箱登录
            if (sha1($password) !== $member_obj['password']) return -4;
        }

        $result = $this->autoLogin($member_obj, $module);

        return $result ? $member_obj : 0;
    }

    /**
     * 更新用户登录信息
     *
     * @param        $member_obj
     * @param string $module
     *
     * @return mixed
     */
    private function autoLogin($member_obj, string $module)
    {
        // 记录登录SESSION和COOKIES
        $auth_login = [
            'uuid'        => $member_obj->id,
            'client_type' => $member_obj->appinit_type,
            'login_time'  => time()
        ];

        $auth_login_sign = data_auth_sign($auth_login);

        session($module . '_login', $auth_login);
        session($module . '_login_sign', $auth_login_sign);

        return $member_obj->save();
    }

    /**
     * 获取上一级
     * @param     $member_id
     * @param int $type
     * @return array
     */
    public function diguiPar($member_id, $type = 2)
    {
        $memberList = $this->findParentObject1($member_id);

        // 要把列表倒叙排序
        if ($type == 1) {
            // 找到上级是节点的，找到后停止循环 ，分成使用
            $memberListNew = [];
            $member_group_list = Db::query("select * from think_member_group");

            // 判断如果是节点 上级节点不
            for ($i = count($memberList) - 1; $i >= 0; $i--) {
                // 判断自己等级是最大级的时候
                $memberListNew[] = $memberList[$i];
                if ($member_group_list[count($member_group_list) - 1]['level'] == $memberList[$i]['level']) {
                    // 最大等级跳出
                    //break;
                }
            }
            sort($memberListNew);
            return $memberListNew;
        } else {
            return $memberList;
        }
    }

    //查找上级
    public function findParentObject1($member_id)
    {
        $memberInfo = Db::name('member')
            ->where('id', $member_id)
            ->find();
        $ids = str_replace('[', '', $memberInfo['parent_ids']);
        $ids = str_replace(']', '', $ids);
        $memberList = Db::name('member')
            ->field("think_member.*,think_member_group.level")
            ->join("think_member_group", 'think_member.member_group_id = think_member_group.id', 'left')
            ->where('think_member.id', 'in', $ids)
            ->select()->toArray();
        return $memberList;
    }

    /**
     * 升级
     * @param int $member_id
     * @param int $max_level
     */
    public function levelUp($member_id, $max_level = 4)
    {
        // 查询团队人数与营业额
        // 先判断自己是否是节点
        $memberInfo = Db::query("select think_member.*,think_member_group.level from think_member  left join think_member_group on think_member.member_group_id = think_member_group.id where think_member.id= $member_id");// 用户列表

        $memberInfo = $memberInfo[0];
        // 最高等级，直接跳出
        if ($memberInfo['level'] == $max_level) return false;
        if ($memberInfo['member_group_id'] == 0) {
            // 如果等级为0 则判断 是否购买过
            $is_but_limit = Db::name('bill')
                ->where('member_id', $memberInfo['id'])
                ->where(function ($query) {
                    $query->where('bill_type_id', 5)
                        ->whereor('bill_type_id', 22);
                })
                ->find();
            if (empty($is_but_limit)) {
                // 没有购买过
                Log::record("执行UID" . $memberInfo['id'] . "没有购买过额度，不触发升级 ");
                return false;
            }
        }

        // 直推人数
        $inviteCount = $memberInfo['invite_count'] + 1;
        // 团队有效人数
        $memberCount = $memberInfo['team'] + 1;
        // 下级等级个数
        if ($memberInfo['member_group_id'] == 0) {
            // 下级列表
            $child_member_ids = Db::name('member')
                //->where("parent_ids", 'like', '%[' . $memberInfo['id'] . ']%')
                ->where("referee_id", $memberInfo['id'])
                ->column('id');

            // 下级等级个数
            $nextMemberCount = Db::name("bill")
                ->where("member_id", 'in', $child_member_ids)
                ->where(function ($query) {
                    $query->where('bill_type_id', 5)
                        ->whereor('bill_type_id', 22);
                })
                ->group('member_id')
                ->count();
            $nextMemberCount = $nextMemberCount + 1;
        } else {
            // 下级等级个数
            $nextMemberCount = Db::name("member")
                //->where("parent_ids", 'like', '%[' . $memberInfo['id'] . ']%')
                ->where("referee_id", $memberInfo['id'])
                ->where("member_group_id", '>=', $memberInfo['member_group_id'])
                ->count();
        }

        $where = [
            ['team', '<=', $memberCount],
            ['referee', '<=', $inviteCount],
            ['zt_level_num', '<=', $nextMemberCount]
        ];

        //  符合现在升级条件的第一个等级
        $member_group_id = Db::name('member_group')
            ->where($where)
            ->where('id', '<>', 7)
            ->order("id desc")
            ->value('id');
        $member_group_id_sql = Db::name('member_group')
            ->where($where)
            ->where('id', '<>', 7)
            ->fetchSql(true)
            ->order("id desc")
            ->value('id');
        Log::record("执行UID" . $memberInfo['id'] . "升级sql：" . $member_group_id_sql);

        // 根据现有等级查询下一等级升级所需条件
        if ($member_group_id) {
            $level = Db::name("member_group")->where("id", $member_group_id)->value("level");
            if ($level > $memberInfo['level']) {
                Log::record("执行UID" . $memberInfo['id'] . "原等级，" . $level . ",升级到" . $memberInfo['id']);
                $res = Db::name('member')
                    ->where('id', $memberInfo['id'])
                    ->update(['member_group_id' => $member_group_id]);
                if (!$res) throw new Exception("插入错误");
            }
        }
    }

}

